package com.loong.android.sqlite.builder;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;

import com.loong.android.sqlite.CommonEntity;
import com.loong.android.sqlite.data.DbData;
import com.loong.android.sqlite.utils.DataBaseUtils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * SQLite数据库查询构造类
 */
public class QueryBuilder {
    private String querySql = "";
    private String queryFields = "*";
    private String queryFilter = "1";
    private String queryOrder = "";
    private String queryLimit = "";
    private String tableName = "";
    private String dbName = "";
    private final SQLiteDatabase database;

    public QueryBuilder(String dbName, String tableName) {
        DbData data = DataBaseUtils.getDbData(dbName);
        this.database = data != null ? data.getSqLiteDatabase() : null;
        this.dbName = dbName;
        this.tableName = tableName;
    }

    /**
     * 创建查询
     *
     * @param dbName 数据库名称
     * @param tableName 表名称
     */
    public static QueryBuilder build(String dbName, String tableName) {
        return new QueryBuilder(dbName, tableName);
    }

    /**
     * 添加查询字段，*号表示查询表中的所有字段
     *
     * @param fieldNames 字段名称，可拓展参数，可传入多个字段名称。
     */
    public QueryBuilder fields(String... fieldNames) {
        if (fieldNames == null || fieldNames.length <= 0) return this;
        for (String s : fieldNames) {
            if (queryFields == null || queryFields.equals("") || queryFields.equals("*")) {
                queryFields = s;
            } else {
                queryFields += "," + s;
            }
        }
        return this;
    }

    /**
     * 添加查询条件
     *
     * @param conditionContents 查询条件内容，如:"column = 'abc' or abc = 1"，支持传入任意多个查询条件，多个查询条件之间是"and"的关系。
     */
    public QueryBuilder conditions(String... conditionContents) {
        if (conditionContents == null || conditionContents.length <= 0) return this;
        for (String s : conditionContents) {
            if (queryFilter == null || queryFilter.equals("") || queryFilter.equals("1")) {
                queryFilter = "(" + s + ")";
            } else {
                queryFilter += " and (" + s + ")";
            }
        }
        return this;
    }

    /**
     * 添加查询排序
     *
     * @param fieldName   用作排序的字段名称
     * @param type   false=升序；true=降序
     */
    public QueryBuilder sort(String fieldName, boolean type) {
        if (queryOrder == null || queryOrder.equals("")) {
            queryOrder = fieldName + (type ? " DESC" : " ASC");
        } else {
            queryOrder += "," + fieldName + (type ? " DESC" : " ASC");
        }
        return this;
    }

    /**
     * 添加查询排序
     *
     * @param sortContents 排序命令内容，可拓展参数，可传入多个值。
     */
    public QueryBuilder sort(String... sortContents) {
        if(sortContents == null || sortContents.length <= 0) return this;
        for (String sortContent : sortContents) {
            if (queryOrder == null || queryOrder.equals("")) {
                queryOrder = sortContent;
            } else {
                queryOrder += ", " + sortContent;
            }
        }
        return this;
    }

    /**
     * 添加查询的限制数量
     *
     * @param size 查询限制数量
     */
    public QueryBuilder limit(long size) {
        queryLimit = "" + size;
        return this;
    }

    /**
     * 添加查询的限制数量
     *
     * @param offset 查询索引偏移
     * @param size 查询限制数量
     */
    public QueryBuilder limit(long offset, long size) {
        queryLimit = offset + ", " + size;
        return this;
    }

    private String makeQuerySql() {
        querySql = "SELECT " + queryFields + " FROM " + tableName + " WHERE " + queryFilter +
                (queryOrder.equals("") ? "" : " ORDER BY " + queryOrder) +
                (queryLimit.equals("") ? "" : " LIMIT " + queryLimit);
        return querySql;
    }

    /**
     * 执行查询，返回表数据实体数组。
     *
     * @param tableEntityClass 表的实体类对象
     */
    public <T> T[] query(Class<?> tableEntityClass) {
        if (database == null || tableEntityClass == null) return null;
        Field[] fieldList = tableEntityClass.getDeclaredFields();
        if (fieldList == null || fieldList.length <= 0) return null;

        Cursor cursor = database.rawQuery(makeQuerySql(), null);

        List<Object> outputList = new ArrayList<>();
        if (cursor != null) {
            while (cursor.moveToNext()) {

                T obj = null;
                try {
                    obj = (T) tableEntityClass.newInstance();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (obj == null) continue;

                for (Field field : fieldList) {
                    if (field == null) continue;
                    field.setAccessible(true);
                    String name = field.getName();
                    if (TextUtils.isEmpty(name) || name.length() <= 3) continue;
                    if (!name.substring(0, 3).equalsIgnoreCase("db_")) continue;
                    if (name.equals(CommonEntity.ID_KEY)) name = CommonEntity.ID_COLUMN_KEY;
                    String type = field.getType().getSimpleName();
                    if (type == null) continue;
                    int index = cursor.getColumnIndex(name);
                    if (index < 0) continue;
                    try {
                        if (type.equalsIgnoreCase("string")) {
                            field.set(obj, cursor.getString(index));
                        } else if (type.equalsIgnoreCase("boolean")) {
                            field.set(obj, cursor.getLong(index) == 1L);
                        } else if (type.equalsIgnoreCase("short")) {
                            field.set(obj, cursor.getShort(index));
                        } else if (type.equalsIgnoreCase("integer")) {
                            field.set(obj, cursor.getInt(index));
                        } else if (type.equalsIgnoreCase("long")) {
                            field.set(obj, cursor.getLong(index));
                        } else if (type.equalsIgnoreCase("float")) {
                            field.set(obj, cursor.getFloat(index));
                        } else if (type.equalsIgnoreCase("double")) {
                            field.set(obj, cursor.getDouble(index));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                outputList.add(obj);
            }
            cursor.close();
        }
        if(outputList.size() > 0) {
            T[] entities = (T[]) Array.newInstance(tableEntityClass, outputList.size());
            for (int i = 0; i < outputList.size(); i++) {
                entities[i] = (T) outputList.get(i);
            }
            return entities;
        }
        return null;
    }

    /**
     * 取查询命令语句
     */
    public String toString() {
        return querySql;
    }
}
